package Java2Test.mythread.threadtest7;

import java.util.*;

public class MyRunnable implements Runnable {
    private final ArrayList<Integer> list; // 共享奖池，多线程共享的资源，需同步保护

    public MyRunnable(ArrayList<Integer> list) {
        this.list = list;
    }

    ArrayList<Integer> list1 = new ArrayList<>(); // 抽奖箱1专属的奖品存储列表
    ArrayList<Integer> list2 = new ArrayList<>(); // 抽奖箱2专属的奖品存储列表
    static Integer max = 0; // 存储奖池初始的最大值（实际场景应避免提前固定，需动态对比）

    @Override
    public void run() {
        // 逻辑难点1：提前获取奖池初始最大值，若抽奖过程中奖品被抽走，此值可能失效
        // 问题：奖池被修改后，初始max无法反映真实的全局最大，建议动态对比两个抽奖箱的最大值
        Integer max = Collections.max(list);

        while (true) {
            // 逻辑难点2：同步锁的作用与范围
            // 用类锁保证多线程对共享资源（奖池、结果列表）操作的原子性，避免数据混乱
            synchronized (MyRunnable.class) {
                // 逻辑难点3：原子性检查 + 结果处理的顺序
                // 先判断奖池是否为空，再处理结果，避免“抽奖”和“统计”操作交叉导致的竞态条件
                if (list.isEmpty()) {
                    // 逻辑难点4：线程身份识别与结果输出
                    // 根据线程名称区分抽奖箱，处理各自的结果统计
                    if (Thread.currentThread().getName().equals("抽奖箱1")) {
                        int sum = 0;
                        if (list1.isEmpty()) {
                            System.out.println("抽奖箱1中没有抽到奖");
                        } else {
                            Integer max1 = Collections.max(list1);
                            for (int i = 0; i < list1.size(); i++) {
                                sum += list1.get(i);
                            }
                            System.out.println("在此次抽奖过程中,抽奖箱1" +
                                    "总共产生了" + list1.size() +
                                    "个奖项.分别为" + list1 +
                                    ",最高奖项为" + Collections.max(list1) +
                                    "元,总金额为" + sum + "元");

                            // 逻辑难点5：最大奖项判断的时机与准确性
                            // 依赖初始奖池的max，若抽奖过程中最大奖被抽走，逻辑会失效
                            if (Objects.equals(max1, max)) {
                                System.out.println("在此次抽奖过程中，抽奖箱1中产生了最大奖项，该奖项金额为" + max1 + "元");
                                break; // 仅当前线程break，另一个线程仍需处理
                            }
                        }

                    } else if (list2.isEmpty()) {
                        System.out.println("抽奖箱2中没有抽到奖");
                    } else {
                        Integer max2 = Collections.max(list2);
                        int sum = 0;
                        for (int i = 0; i < list2.size(); i++) {
                            sum += list2.get(i);
                        }
                        System.out.println("在此次抽奖过程中,抽奖箱2" +
                                "总共产生了" + list2.size() +
                                "个奖项.分别为" + list2 +
                                ",最高奖项为" + Collections.max(list2) +
                                "元,总金额为" + sum + "元");
                        // 同样依赖初始max，存在逻辑漏洞
                        if (Objects.equals(max2, max)) {
                            System.out.println("在此次抽奖过程中，抽奖箱2中产生了最大奖项，该奖项金额为" + max2 + "元");
                            break; // 仅当前线程break，需保证另一个线程也能正常退出
                        }
                    }
                    break; // 奖池空时退出循环，但可能存在线程未完整处理结果的情况
                }
                // 逻辑难点6：随机抽奖与资源分配
                // 随机抽取奖品并按线程名称存入对应列表，需保证操作的原子性（已由同步锁保护）
                int randomIndex = new Random().nextInt(list.size());
                Integer prize = list.remove(randomIndex);
                if (Thread.currentThread().getName().equals("抽奖箱1")) {
                    list1.add(prize);
                } else {
                    list2.add(prize);
                }
                // 逻辑难点7：线程调度与锁竞争的影响
                // 同步块内休眠会“占用锁”，延长当前线程持有锁的时间，影响其他线程的执行节奏
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            // 同步块外：锁已释放，其他线程可竞争锁，休眠不影响锁逻辑
        }
    }
}